app.factory("User", ["AppSingleData", "$rootScope", "$http", "$token", "$location", "$canceler", "$exception", "$notify", "$timeout", function (AppSingleData, $rootScope, $http, $token, $location, $canceler, $exception, $notify, $timeout) {
    
    function User(options) {
        AppSingleData.call(this, options);
        this.type = "user";
    };

    User.prototype = Object.create(AppSingleData.prototype);
    User.prototype.constructor = User;

    User.prototype.distances = [
            { name: "quartier (1 km)", value: 1000 },
            { name: "centre ville (2 km)", value: 2000 },
            { name: "ville (5 km)", value: 5000 },
            { name: "alentour (10 km)", value: 10000 }
    ];

    User.prototype.save = function(){
        var self = this;
        return $timeout(function(){
            $location.path("/");

            $notify.show(self.data._id ? "Mise à jour en cours..." : "Création en cours...", 0);

            return $token.get().then(function (token) {
                return $http.post("/api/image/user/picto", { datauri: self.data.picto.src }, { params: { token: token }, timeout: $canceler.create(10).promise }).then(function (res) {
                    self.data.picto.src = res.data.src;

                    return $http.post("/api/user/save", self.data, { params: { token: token }, timeout: $canceler.create().promise }).then(function(){
                        $rootScope.$broadcast("/api/user/save");
                        $notify.hide();
                    });
                });
            });
        }).catch(function (error) {
            $exception.show(error);
        });
    };

    return User;

} ]);

app.factory("Alert", ["AppSingleData", "$rootScope", "$http", "$token", "$location", "$canceler", "$exception", "$confirm", "$notify", "$q","$timeout", function (AppSingleData, $rootScope, $http, $token, $location, $canceler, $exception, $confirm, $notify, $q, $timeout) {
    
    function Alert(options) {
        AppSingleData.call(this, options);
        this.type = "alert";
        this.progress = 0;
    };

    Alert.prototype = Object.create(AppSingleData.prototype);
    Alert.prototype.constructor = Alert;

    Alert.prototype.maturities = [
        { name: "1 heure", value: "1h" },
        { name: "3 heures", value: "3h" },
        { name: "6 heures", value: "6h" },
        { name: "1 jour", value: "1d" },
        { name: "3 jours", value: "3d" },
        { name: "10 jours", value: "3d" }
    ];
   
    Alert.prototype.like = function(){
        var self = this;

        return $timeout(function(){
            $location.path("/");

            return $token.get().then(function (token) {

                var req = { alertId: self.data._id };
                return $http.post("/api/alert/like", req, { params: { token: token }, timeout: $canceler.create().promise }).then(function(){
                    self.data.like = true;
                    $rootScope.$broadcast("/api/alert/like");
                    return $confirm.show("L'alerte est dans vos favoris.").then(function () {
                    }, function () {
                        return $http.post("/api/alert/like/delete", req, { params: { token: token}, timeout: $canceler.create().promise });
                    });
                });
            });
        }).catch(function (error) {
            $exception.show(error);
        });
    };

    Alert.prototype.gotoAlert = function () {
        this.data.read = true;
        $location.path("alert/" + this.data._id);
    };

    Alert.prototype.gotoAlertArchive = function () {
        $location.path("alert/" + this.data._id + "/archive");
    };

    Alert.prototype.gotoShop = function () {
        $location.path("shop/" + this.data.shop.login);
    };

    Alert.prototype.save = function(){
        var self = this;

        return $timeout(function(){
            $location.path("/");

            $notify.show("Création en cours...", 0);

            return $token.get().then(function (token) {
                var promises = [];
                self.data.articles.forEach(function (article) {
                
                    promises.push($timeout(function(){
                        if (!article.image.src || article.image.src.indexOf("api/image") > -1) return;

                        return $http.post("/api/image/alert/image", { datauri: article.image.src, timeout: $canceler.create(10).promise }).then(function (res) {
                            article.image.src = res.data.src;
                        });
                    }));
                });

                return $q.all(promises).then(function () {
                    return $http.post("/api/alert/save", self.data, { params: { token: token}, timeout: $canceler.create().promise }).then(function (res) {
                        $rootScope.$broadcast("/api/alert/save");
                        return $confirm.show("L'alert est créée.").then(function () {
                            self.data = null;
                        }, function () {
                            return $http.post("api/alert/delete", { alertId: res.data._id}, { params: { token: token} });
                        });
                    });
                });
            });
        }).catch(function (error) {
            return $exception.show(error);
        });
    };

    Alert.prototype.removeArticle = function (index) {
        this.data.articles.splice(index, 1);
    };

    Alert.prototype.removeImage = function (index) {
        this.data.articles[index].image = {
            id: null
        };
    };

    Alert.prototype.addImage = function ($image) {
        var article = {
            type: "image",
            image: {
                id: $image
            },
            content: ""
        };
        this.data.articles.push(article);
    };

    return Alert;
} ]);

app.factory("Shop", ["AppSingleData", "$rootScope", "$http", "$token", "$exception", "$location", "$canceler", "$notify", "$confirm", "$timeout", function (AppSingleData, $rootScope, $http, $token, $exception, $location, $canceler, $notify, $confirm, $timeout) {
    function Shop(options) {
        AppSingleData.call(this, options);
        this.type = "shop";
        this.categories = [];
    };

    Shop.prototype = Object.create(AppSingleData.prototype);
    Shop.prototype.constructor = Shop;

    Shop.prototype.save = function(){
        var self = this;

        return $timeout(function(){
            $location.path("/");

            $notify.show(self.data._id ? "Mise à jour en cours..." : "Création en cours...", 0);

            return $token.get().then(function (token) {
                return $http.post("/api/image/shop/picto", { datauri: self.data.picto.src }, { params: { token: token }, timeout: $canceler.create(10).promise }).then(function (res) {
                    self.data.picto.src = res.data.src;

                    return $http.post("/api/image/shop/front", { datauri: self.data.front.src }, { timeout: $canceler.create(20).promise }).then(function (res) {
                        self.data.front.src = res.data.src;

                        return $http.post("/api/shop/save", self.data, { params: { token: token }, timeout: $canceler.create().promise }).then(function(){
                            $rootScope.$broadcast("/api/shop/save");
                            $notify.hide();
                        });
                    });
                });
            });
        }).catch(function (error) {
            $exception.show(error);
        });
    };

    Shop.prototype.subscribeUser = function(){
        var self = this;

        return $timeout(function(){
            $location.path("/");

            $notify.show("Abonnement en cours...", 0);

            return $token.get().then(function (token) {
                var req = { shopId: self.data._id };

                return $http.post("/api/shop/subscribe/user", req, { params: { token: token }, timeout: $canceler.create().promise }).then(function(){
                    $rootScope.$broadcast("/api/shop/subscribe/user");

                    return $confirm.show("Vous êtes abonné à " + self.data.name).then(function () {
                    }, function () {
                        return $http.post("/api/shop/unsubscribe/user", req, { params: { token: token}, timeout: $canceler.create().promise });
                    });
                });
            });
        }).catch(function (error) {
            $exception.show(error);
        });
    };

    Shop.prototype.unSubscribeUser = function(){
        var self = this;

        return $timeout(function(){
            $location.path("/");

            $notify.show("Désabonnement en cours...", 0);

            return $token.get().then(function (token) {
                var req = { shopId: self.data._id };

                return $http.post("/api/shop/unsubscribe/user", req, { params: { token: token }, timeout: $canceler.create().promise }).then(function(){
                    $rootScope.$broadcast("/api/shop/unsubscribe/user");
                    $notify.hide();
                });
            });
        }).catch(function (error) {
            $exception.show(error);
        });
    };

    Shop.prototype.subscribeShop = function(){
        var self = this;

        return $timeout(function(){
            $location.path("/");

            $notify.show("Abonnement en cours...", 0);

            return $token.get().then(function (token) {
                var req = { shopId: self.data._id };

                return $http.post("/api/shop/subscribe/shop", req, { params: { token: token }, timeout: $canceler.create().promise }).then(function(){
                    $rootScope.$broadcast("/api/shop/subscribe/shop");
                    
                    return $confirm.show("Vous êtes abonné à " + self.data.name).then(function () {
                    }, function () {
                        return $http.post("/api/shop/unsubscribe/shop", req, { params: { token: token}, timeout: $canceler.create().promise });
                    });
                });
            });
        }).catch(function (error) {
            $exception.show(error);
        });
    };

    Shop.prototype.unSubscribeShop = function(){
        var self = this;

        return $timeout(function(){
            $location.path("/");

            $notify.show("Abonnement en cours...", 0);

            return $token.get().then(function (token) {
                var req = { shopId: self.data._id };

                return $http.post("/api/shop/unsubscribe/shop", req, { params: { token: token }, timeout: $canceler.create().promise }).then(function(){
                    $rootScope.$broadcast("/api/shop/unsubscribe/shop");
                    $notify.hide();
                });
            });
        }).catch(function (error) {
            $exception.show(error);
        });
    };

    Shop.prototype.loadCity = function () {
        var self = this;
        return $http.get("/api/location/city/"+ self.data.location.city, { timeout: $canceler.create().promise }).then(function (res) {
            self.city = res.data;
        }).catch(function (error) {
            $exception.show(error);
        });
    };

    Shop.prototype.loadGroupCategories = function () {
        var self = this;
        return $http.get("/api/shopcategory", { timeout: $canceler.create().promise }).then(function (res) {
            self.groupCategories = res.data;
        }).catch(function (error) {
            $exception.show(error);
        });
    };

    Shop.prototype.getEmployeesByLogin = function (val) {
        return $token.get().then(function (token) {
            return $http.get("api/users", { params: { login: val, token: token, limit: 10}, timeout: $canceler.create().promise }).then(function (res) {
                return res.data;
            });
        }).catch(function (error) {
            $exception.show(error);
        });
    };

    return Shop;
} ]);

app.factory("appUserCreator", ["User", "$http", "$canceler", "$notify", "$exception", "$location", function (User, $http, $canceler, $notify, $exception, $location) {

    function AppUserCreator() {
        User.call(this, {
            data: {
                login: "",
                password: "",
                contact: {
                    email: ""
                },
                location: {
                    address: "",
                    city: "",
                    postal_code: "",
                    loc: {
                        type: "Point",
                        coordinates: []
                    }
                },
                picto: {
                    src: "/api/image/user/picto/default"
                },
                dates: {
                    creation: null
                },
                shops: {
                    subscriptions: [],        /*liste de boutique abonnées*/
                    near: [],                 /*liste de boutique proche*/
                    employers: []              /*liste de boutique dans laquelle l'utilisateur travaille*/
                },
                users: {
                    subscriptions: [],        /*amis*/
                    near: []                  /*liste d'utilisateur proche*/
                },
                config: {
                    distanceM: 2000
                }
            }
        });
    };

    AppUserCreator.prototype = Object.create(User.prototype);
    AppUserCreator.prototype.constructor = AppUserCreator;

    AppUserCreator.prototype.create = function(){
        var self = this;

        return $timeout(function(){
            $location.path("/login");

            $notify.show("Création en cours...", 0);

            return $http.post("/api/image/user/picto", { datauri: self.data.picto.src }, { timeout: $canceler.create(10).promise }).then(function (res) {
                self.data.picto.src = res.data.src;

                return $http.post("/api/usercreation/create", self.data, { timeout: $canceler.create().promise }).then(function(){
                    $notify.show("Un email de validation vient d'être envoyé.");
                });
            });
        }).catch(function (error) {
            $exception.show(error);
        });
    };

    return new AppUserCreator();

} ]);